/***************************************************************
 * @Copyright(C)    2020-2021, wangchongwei
 * @FileName:       linear_interp.c
 * @Author:         wangchongwei
 * @Version:        0.1.1
 * @LastDate:       2021.8.14
 ************************************************************/

#include "linear_Interp.h"
#include "string.h"

static void _Init(struct LinearInterp *self,
                float *arr_x, float *arr_y,
                uint32_t size)
{
    self->pvt.arr_x = arr_x;
    self->pvt.arr_y = arr_y;
    self->pvt.size = size;
}

static float _Cal(struct LinearInterp *self, float val)
{
    int32_t left = 0, mid = 0;
    int32_t right = self->pvt.size - 1;

    float x0,y0,x1,y1;

    // 二分法
    while (left <= right)
    {
        mid = (left+right)/2;

        if (val<self->pvt.arr_x[mid])
            right = mid - 1;
        else if (self->pvt.arr_x[mid] < val)
            left = mid + 1;
        else 
            break;
    }
    
    // 头尾检测
    if (mid == (self->pvt.size - 1)) {
        mid = mid-1;
    }
    else if (mid == 0){
        mid = 0;
    }
    else{
        mid = (self->pvt.arr_x[mid] <= val)?mid:mid-1; // 中间二分查找出现的情况
    }

    // 3.Linear interpolation
    x0 = self->pvt.arr_x[mid];
    y0 = self->pvt.arr_y[mid];
    x1 = self->pvt.arr_x[mid+1];
    y1 = self->pvt.arr_y[mid+1];

    self->out = y0+(((y1-y0)*(val - x0))/(x1-x0));

    return self->out;
}

void LinearInterp_Create(struct LinearInterp *self)
{
    memset(self , 0 , sizeof(struct LinearInterp));

    self->Init = _Init;
    self->Cal = _Cal;
}
